//----------------------------------------------------------
//	asset file manager
//----------------------------------------------------------
#ifndef ASSETFILEMGR_H
#define ASSETFILEMGR_H

#include "assetfile.h"
#include "../hash/hashlist.h"

class CAssetFile;
class CAssetFileMgr;


//----------------------------------------------------------
//	callback functions to allocate and free memory
//----------------------------------------------------------
typedef void *(*ASSETALLOCFN)( u32 blockType, u32 size, u32 alignment );
typedef void (*ASSETFREEFN)( void *ptr, u32 blockType );

//----------------------------------------------------------
//	callback function for asset enumeration
//	return true to count this in the total returned
//----------------------------------------------------------
typedef bool (*ASSETENUMFN)( CAssetFileMgr *pMgr, void *context, void *ptr, const char *name, HASH type );

//----------------------------------------------------------
//	callback function for memory block enumeration
//----------------------------------------------------------
typedef void (*BLOCKENUMFN)( void *context, const void *blockPtr, u32 length );

//----------------------------------------------------------
//	interface for initializing assets
//----------------------------------------------------------
class IAssetFile
{
public:
	virtual const char	*GetName( HASH hash ) const = 0;
	virtual void		*GetChunk( HASH assetName, LOCID id, u32 *length=0 ) const = 0;
	virtual void		SetupHashList( CStaticHashList *pDict, void *base, bool doItems=true ) const = 0;
};
//----------------------------------------------------------
//	callback functions to initialize/uninitialize an asset
//----------------------------------------------------------
typedef void *(*ASSETINITFN)( IAssetFile *pInit, const CMasterIndexEntry *pEntry, void* context ); 
typedef void (*ASSETUNINITFN)( void *ptr, void* context ); 
typedef void (*ASSETFIXUPFN)( CAssetFileMgr *pMgr, const IAssetFile *pFile, void *ptr, const CMasterIndexEntry *pEntry ); 

#define MAX_ASSET_TYPES	(32)
typedef struct
{
	HASH			typeHash;
	ASSETINITFN		initFn;
	ASSETUNINITFN	uninitFn;
	ASSETFIXUPFN	fixupFn;

} SAssetProcType;

//----------------------------------------------------------
//	asset file manager class
//----------------------------------------------------------
class CAssetFileMgr
{
	friend class ASSETFILETHREAD;
	friend CAssetFileMgr* GetAssetFileMgr();
public:
	CAssetFileMgr( ASSETALLOCFN alloc, ASSETFREEFN free );
	~CAssetFileMgr();

	//----------------------------------------------------------
	//	declare a processable type of asset
	//----------------------------------------------------------
	void	AddAssetType( const char *name, ASSETINITFN ifn, ASSETUNINITFN ufn, ASSETFIXUPFN fixup );

	//----------------------------------------------------------
	//	process - this actually does the loading and stuff
	//----------------------------------------------------------
	void	Process();

	//----------------------------------------------------------
	//	load an asset file (delayed)
	//----------------------------------------------------------
	bool	Load( const char *filename, void* context, bool wait=false );

	//----------------------------------------------------------
	//	unload an asset file
	//----------------------------------------------------------
	void	Unload( const char *filename, bool wait=true );

	//----------------------------------------------------------
	//	unload all asset files
	//----------------------------------------------------------
	void	UnloadAll( bool wait=true );

	//----------------------------------------------------------
	//	enumerate assets
	//----------------------------------------------------------
	u32		EnumerateAssets( ASSETENUMFN fn, void *context, const char *type=0, const char *filename=0 );

	//----------------------------------------------------------
	//	fixup the assets
	//	this allows assets to reference other assets
	//	that they cannt get pointers to from within their
	//	init callbacks
	//----------------------------------------------------------
	u32		FixupAssets( const char *type=0, const char *filename=0 );

	//----------------------------------------------------------
	//	use this in conjunction with the CSaveFile class
	//----------------------------------------------------------
	void	EnumerateMemoryBlocks( BLOCKENUMFN fn, void *context );

	//----------------------------------------------------------
	// find an asset by name and type
	// if inFilename is non-0, only looks in the given file
	//----------------------------------------------------------
	void	*FindAsset( const char *assetName, const char *assetType=0, const char *inFilename=0 );
	void	*FindAsset( HASH assetHash, const char *assetType, const char *inFilename=0 );
	void	*FindAsset( HASH assetHash, HASH assetType=0, const char *inFilename=0 );

protected:

	//----------------------------------------------------------
	//	find an asset
	//----------------------------------------------------------
	void	*FindAsset( HASH assetName, HASH assetType, CAssetFile *pFile );

	//----------------------------------------------------------
	//	find an asset type
	//----------------------------------------------------------
	SAssetProcType *FindAssetType( HASH typeHash );

	//----------------------------------------------------------
	//	info function
	//----------------------------------------------------------
	void		Info( const char *fmt, ... );

	//----------------------------------------------------------
	//	load the next asset file
	//----------------------------------------------------------
	bool		LoadNextFile();

	//----------------------------------------------------------
	//	initialize the next asset file
	//----------------------------------------------------------
	bool		InitializeNextFile();

	//----------------------------------------------------------
	//	unload the next asset file
	//----------------------------------------------------------
	bool		UnloadNextFile();

	//----------------------------------------------------------
	//	find an asset file
	//----------------------------------------------------------
	CAssetFile	*FindFile( const char *filename, CAssetFile **pList );
	CAssetFile	*FindFile( const char *filename, bool onlyLoaded=true );

	//----------------------------------------------------------
	//	enumerate
	//----------------------------------------------------------
	u32			EnumerateAssets( ASSETENUMFN fn, void *context, HASH type, const CAssetFile *pFile );

	//----------------------------------------------------------
	//	fixup
	//----------------------------------------------------------
	u32			FixupAssets( HASH type, const CAssetFile *pFile );

protected:
	//----------------------------------------------------------
	//	asset allocation
	//----------------------------------------------------------
	ASSETALLOCFN		allocfn;
	ASSETFREEFN			freefn;

	void				*context;

	//----------------------------------------------------------
	// this is a list of all available asset files
	//----------------------------------------------------------
	CAssetFile			*pAssets;
	CAssetFile			*pFilesToInit;
	CAssetFile			*pFilesToLoad;
	CAssetFile			*pFilesToUnload;

	//----------------------------------------------------------
	//	asset type lookup table
	//----------------------------------------------------------
	u32					numAssetTypes;
	SAssetProcType		assetTypes[MAX_ASSET_TYPES];
};

#endif
